R"( do

-- This Lua code sets up the "environment" for sandboxed game code to run in.
--   It deletes all global variables except a whitelist, and implements some functionality
--   with safety wrappers.
-- This code is always executed first in the Lua environment;
--   It is included into bllua3.cpp at compile-time, hardcoded in bllua3.dll,
--   and eval'd during initialization, before the environment is exposed to any user code.
--   Because of this, it is impossible for user code to access unsafe functionality
--   except through the functions provided here.

-- Utility: Convert a list of strings into a map of string->true
local tflip = function(t) local u = {}; for _, n in ipairs(t) do u[n] = true end; return u; end

-- Save banned global variables for wrapping with safe functions
local old_io = io
local old_require = require
local old_os = os
local old_debug = debug

-- Remove all global variables except a whitelist
local ok_names = tflip {
	"_G", "ts",
	"string", "table", "math", "coroutine", "bit",
	"unpack", "pairs", "ipairs",
	"error", "assert", "pcall",
	"type", "tostring", "tonumber",
	"loadstring",
	"getmetatable", "setmetatable", "rawget", "rawset",
}
local names = {}
for n, _ in pairs(_G) do if not ok_names[n] then table.insert(names, n) end end
for _, n in ipairs(names) do _G[n] = nil end

-- Sanitize a file path to point only to allowed files within the blockland directory
local safe_dirs = tflip{"add-ons", "base", "config", "saves", "screenshots", "shaders"}
local safe_dirs_readonly = tflip{"luainc"}
local safe_exts = tflip{
	"txt", "zip", "bls", "blb",
	"png", "jpg", "ogg", "wav",
	"dts", "dsq", "dif", "ter",
	"gui", "cs", "mis", "dso", "glsl",
	"lua", "asm", "s", "bin",
	"dat", "log", "out", "html", "xml", "json",
}
local function safe_path(fn, readonly)
	fn = fn:gsub("\\", "/")
	fn = fn:gsub("^ +", "")
	fn = fn:gsub(" +$", "")
	local ic = fn:find("[^a-zA-Z0-9_%-/ %.]"); if ic then return nil, "Filename \""..fn.."\" contains invalid character \'"..fn:sub(ic, ic).."\' at position "..ic end
	if fn:find("^%.") or fn:find("%.%.") or fn:find(":") or fn:find("^/") then return nil, "Filename \""..fn.."\" contains invalid sequence", errn+1 end
	local dir = fn:match("^([^/]+)/")
	if (not dir) or (
		(not safe_dirs[dir:lower()]) and
		((not readonly) or (not safe_dirs_readonly[dir:lower()]))
	) then return nil, "filename is in disallowed directory "..(dir or "nil") end
	--local ext = fn:match("%.([^/%.]+)$"); if (not ext) or (not safe_exts[ext:lower()]) then return nil, "Filename \""..fn.."\" has disallowed extension \""  ..(ext or "").."\"" end
	return fn, nil
end

-- Provide limited I/O using safe paths
function _bllua_io_open(fn, md)
	md = md or "r"
	local readonly = md=="r" or md=="rb"
	local fns, err = safe_path(fn, readonly)
	if fns then return old_io.open(fns, md) else return nil, err end
end
function _bllua_io_type(fn)
	return old_io.type(fn)
end

-- Allow requiring certain external packages
--local secure_packages = tflip{ "socket" }--, "ffi" }
function requiresecure(mod)
	--if secure_packages[mod] then
	--	return old_require(mod)
	--else
	--	error("require: invalid or non-whitelisted module "..mod, 3)
	--end
	return old_require(mod)
end

-- Provide limited debug facilities
debug = {
	traceback = old_debug.traceback,
	getinfo = old_debug.getinfo,
}

ts.echo("    Lua env loaded")

end )"